package com.medusa.aps.business.modules.modeling.mp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.aps.business.model.constant.RedisConstants;
import com.medusa.aps.business.model.enums.AuxiliaryStatus;
import com.medusa.aps.business.model.pagination.Page;
import com.medusa.aps.business.modules.modeling.model.input.AuxiliaryDataDTO;
import com.medusa.aps.business.modules.modeling.model.input.AuxiliaryDataParam;
import com.medusa.aps.business.modules.modeling.mp.entity.AuxiliaryData;
import com.medusa.aps.business.modules.modeling.mp.entity.WorkingProcedureAuxiliary;
import com.medusa.aps.business.modules.modeling.mp.mapper.AuxiliaryDataMapper;
import com.medusa.aps.business.modules.modeling.mp.service.AuxiliaryDataService;
import com.medusa.aps.business.modules.modeling.mp.service.WorkingProcedureAuxiliaryService;
import com.medusa.aps.business.util.PercentageScheduleUtils;
import com.medusa.aps.business.common.model.resp.SystemCode;
import com.medusa.aps.business.common.redis.annotation.Redisson;
import com.medusa.aps.business.global.model.exception.GlobalException;
import com.medusa.aps.business.global.model.exception.collector.DistinctValidator;
import com.medusa.aps.business.global.model.exception.collector.ErrorCollector;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 辅助资料服务实现类
 *
 * @author yuxh
 * @since 2023-08-14 17:37:41
 */
@Service("auxiliaryDataService")
public class AuxiliaryDataServiceImpl extends ServiceImpl<AuxiliaryDataMapper, AuxiliaryData> implements AuxiliaryDataService {

    @Resource
    private AuxiliaryDataService auxiliaryDataService;
    @Resource
    private WorkingProcedureAuxiliaryService workingProcedureAuxiliaryService;

    /**
     * 分页查询辅助资源
     *
     * @param auxiliaryDataParam 辅助资源查询参数
     * @return 分页列表
     */
    @Override
    public Page<AuxiliaryData> pageAuxiliaryData(AuxiliaryDataParam auxiliaryDataParam) {
        return auxiliaryDataService.lambdaQuery()
                .in(CollUtil.isNotEmpty(auxiliaryDataParam.getIds()), AuxiliaryData::getId, auxiliaryDataParam.getIds())
                .like(StringUtils.hasText(auxiliaryDataParam.getAuxiliaryResourceCoding()), AuxiliaryData::getAuxiliaryResourceCoding, auxiliaryDataParam.getAuxiliaryResourceCoding())
                .like(StringUtils.hasText(auxiliaryDataParam.getAuxiliaryResourceName()), AuxiliaryData::getAuxiliaryResourceName, auxiliaryDataParam.getAuxiliaryResourceName())
                .like(StringUtils.hasText(auxiliaryDataParam.getCreator()), AuxiliaryData::getCreator, auxiliaryDataParam.getCreator())
                .eq(auxiliaryDataParam.getType() != null, AuxiliaryData::getType, auxiliaryDataParam.getType())
                .eq(auxiliaryDataParam.getStatus() != null, AuxiliaryData::getStatus, auxiliaryDataParam.getStatus())
                .eq(auxiliaryDataParam.getDataSource() != null, AuxiliaryData::getDataSource, auxiliaryDataParam.getDataSource())
                .between(auxiliaryDataParam.getCreateTime().getStartTime() != null && auxiliaryDataParam.getCreateTime().getEndTime() != null,
                        AuxiliaryData::getCreateTime,
                        auxiliaryDataParam.getCreateTime().getStartTime(),
                        auxiliaryDataParam.getCreateTime().getEndTime())
                .in(CollUtil.isNotEmpty(auxiliaryDataParam.getAuxiliaryResourceCodings()), AuxiliaryData::getAuxiliaryResourceCoding, auxiliaryDataParam.getAuxiliaryResourceCodings())
                .orderByDesc(AuxiliaryData::getCreateTime)
                .orderByDesc(AuxiliaryData::getId)
                .page(auxiliaryDataParam);
    }

    /**
     * 分页查询辅助资源
     *
     * @param auxiliaryDataParam 辅助资源查询参数
     * @return 分页列表
     */
    @Override
    public Page<AuxiliaryData> listAuxiliaryData(AuxiliaryDataParam auxiliaryDataParam) {
        return auxiliaryDataService.lambdaQuery()
                .in(CollUtil.isNotEmpty(auxiliaryDataParam.getIds()), AuxiliaryData::getId, auxiliaryDataParam.getIds())
                .like(StringUtils.hasText(auxiliaryDataParam.getAuxiliaryResourceCoding()), AuxiliaryData::getAuxiliaryResourceCoding, auxiliaryDataParam.getAuxiliaryResourceCoding())
                .like(StringUtils.hasText(auxiliaryDataParam.getAuxiliaryResourceName()), AuxiliaryData::getAuxiliaryResourceName, auxiliaryDataParam.getAuxiliaryResourceName())
                .like(StringUtils.hasText(auxiliaryDataParam.getCreator()), AuxiliaryData::getCreator, auxiliaryDataParam.getCreator())
                .eq(auxiliaryDataParam.getType() != null, AuxiliaryData::getType, auxiliaryDataParam.getType())
                .ne( AuxiliaryData::getStatus, AuxiliaryStatus.SCRAP)
                .eq(auxiliaryDataParam.getDataSource() != null, AuxiliaryData::getDataSource, auxiliaryDataParam.getDataSource())
                .between(auxiliaryDataParam.getCreateTime().getStartTime() != null && auxiliaryDataParam.getCreateTime().getEndTime() != null,
                        AuxiliaryData::getCreateTime,
                        auxiliaryDataParam.getCreateTime().getStartTime(),
                        auxiliaryDataParam.getCreateTime().getEndTime())
                .in(CollUtil.isNotEmpty(auxiliaryDataParam.getAuxiliaryResourceCodings()), AuxiliaryData::getAuxiliaryResourceCoding, auxiliaryDataParam.getAuxiliaryResourceCodings())
                .orderByDesc(AuxiliaryData::getCreateTime)
                .orderByDesc(AuxiliaryData::getId)
                .page(auxiliaryDataParam);
    }

    /**
     * 批量新增辅助资源
     *
     * @param auxiliaryDataCreates 辅助资料数据
     */
    @Override
    @Redisson(name = RedisConstants.AUXILIARY_DATA_LOCK_KEY, waitTime = 1)
    public void saveBatchAuxiliaryData(List<AuxiliaryDataDTO> auxiliaryDataCreates) {
        validator(auxiliaryDataCreates);
        List<AuxiliaryData> auxiliaries = auxiliaryDataCreates.stream()
                .map(AuxiliaryDataDTO::newAuxiliaryData)
                .toList();
        auxiliaryDataService.saveBatch(auxiliaries);
    }

    /**
     * 修改辅助资源
     *
     * @param auxiliaryDataDTO 辅助资料数据
     */
    @Override
    @Redisson(name = RedisConstants.AUXILIARY_DATA_LOCK_KEY, waitTime = 1)
    public void updateAuxiliaryData(AuxiliaryDataDTO auxiliaryDataDTO) {
        Integer auxiliaryId = auxiliaryDataDTO.getId();
        AuxiliaryData auxiliaryData = this.getById(auxiliaryId);
        if (auxiliaryData == null) {
            throw SystemCode.PARAM_VALID_ERROR.msgEx("该辅助资源不存在");
        }
        auxiliaryData.setAuxiliaryResourceName(auxiliaryDataDTO.getAuxiliaryResourceName())
                .setType(auxiliaryDataDTO.getType())
                .setStatus(auxiliaryDataDTO.getStatus())
                .setDescription(auxiliaryDataDTO.getDescription())
                .setAuxiliaryResourceCoding(auxiliaryData.getAuxiliaryResourceCoding());
        auxiliaryDataService.updateById(auxiliaryDataDTO.newAuxiliaryData());
    }

    /**
     * 批量删除辅助资源
     *
     * @param ids id集合
     */
    @Override
    @Redisson(name = RedisConstants.AUXILIARY_DATA_LOCK_KEY, waitTime = 1)
    public void deleteBatch(List<Integer> ids) {
        List<AuxiliaryData> auxiliaryDataList = auxiliaryDataService.lambdaQuery()
                .select(AuxiliaryData::getAuxiliaryResourceName, AuxiliaryData::getAuxiliaryResourceCoding, AuxiliaryData::getStatus)
                .in(AuxiliaryData::getId, ids)
                .list();
        if (CollUtil.isEmpty(auxiliaryDataList)) {
            throw new GlobalException(SystemCode.DATA_NOT_EXIST.getMsg());
        }
        PercentageScheduleUtils.valid(
                auxiliaryDataList.stream()
                        .filter(item -> item.getStatus() == AuxiliaryStatus.USING)
                        .collect(Collectors.toList()),
                AuxiliaryData::getAuxiliaryResourceCoding,
                "辅助资源编码:【{}】为正在使用，删除失败"
        );
        //工序占用校验
        PercentageScheduleUtils.valid(
                workingProcedureAuxiliaryService
                        .lambdaQuery()
                        .select(WorkingProcedureAuxiliary::getAuxiliaryDataCoding)
                        .in(WorkingProcedureAuxiliary::getAuxiliaryId, ids)
                        .list(),
                WorkingProcedureAuxiliary::getAuxiliaryDataCoding,
                "辅助资源编码:【{}】被工序占用，删除失败"
        );
        auxiliaryDataService.removeBatchByIds(ids);
    }


    private void validator(List<AuxiliaryDataDTO> auxiliaryDataCreates) {
        ErrorCollector errorCollector = DistinctValidator.valid(auxiliaryDataCreates, AuxiliaryDataDTO::getAuxiliaryResourceCoding, "辅助资源编码");
        if (errorCollector.hasError()) {
            throw new GlobalException(errorCollector.toString());
        }
        List<String> auxiliaryResourceCodings = auxiliaryDataCreates.stream().map(AuxiliaryDataDTO::getAuxiliaryResourceCoding).toList();
        List<AuxiliaryData> auxiliaryDataList = auxiliaryDataService.lambdaQuery()
                .select(AuxiliaryData::getAuxiliaryResourceCoding)
                .in(AuxiliaryData::getAuxiliaryResourceCoding, auxiliaryResourceCodings)
                .list();
        if (CollectionUtils.isEmpty(auxiliaryDataList)) {
            return;
        }
        Set<String> auxiliaryResourceCodingDbs = auxiliaryDataList.stream().map(AuxiliaryData::getAuxiliaryResourceCoding).collect(Collectors.toSet());
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < auxiliaryDataCreates.size(); i++) {
            AuxiliaryDataDTO auxiliaryDataDTO = auxiliaryDataCreates.get(i);
            if (auxiliaryResourceCodingDbs.contains(auxiliaryDataDTO.getAuxiliaryResourceCoding())) {
                stringBuilder.append(StrUtil.format("第{}行：辅助资源编码【{}】系统已存在;", i + 1, auxiliaryDataDTO.getAuxiliaryResourceCoding()));
            }
        }
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        throw new GlobalException(stringBuilder.toString());
    }

}



